package Q1;

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;

import java.awt.event.ActionListener;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Bank
 */
public class Bank extends JFrame {

    /**
     * Consumer service queue
     */
    private final BlockingQueue<Customer> queue = new LinkedBlockingQueue<>();

    /**
     * Counter personnel array
     */
    private final Teller[] tellers = new Teller[3];

    /**
     * The button represents the counter personnel
     */
    private final JToggleButton[] btnWindows = new JToggleButton[3];

    /**
     * This JLabel is a temporary variable
     */
    private final JLabel lblMsg;

    /**
     * This JLabel represents the current number of people in the queue
     */
    private final JLabel lblCustomerCount;

    /**
     * This JLabel represents the last customer number (or id)
     */
    private final JLabel lblLastCustomer;

    /**
     * Auto add customer thread
     */
    private Thread autoAddCustomerThread;

    /**
     * Create the windows frame
     */
    public Bank() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 566, 409);
        final JPanel contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        final JPanel panel = new JPanel();
        contentPane.add(panel, BorderLayout.NORTH);

        final JToggleButton btnWindow1 = new JToggleButton("窗口-1");
        btnWindow1.setName("0");
        btnWindow1.setPreferredSize(new Dimension(120, 80));
        btnWindows[0] = btnWindow1;
        panel.add(btnWindow1);

        final JToggleButton btnWindow2 = new JToggleButton("窗口-2");
        btnWindow2.setName("1");
        btnWindow2.setPreferredSize(new Dimension(120, 80));
        btnWindows[1] = btnWindow2;
        panel.add(btnWindow2);

        final JToggleButton btnWindow3 = new JToggleButton("窗口-3");
        btnWindow3.setName("2");
        btnWindow3.setPreferredSize(new Dimension(120, 80));
        btnWindows[2] = btnWindow3;
        panel.add(btnWindow3);

        final JPanel panel_1 = new JPanel();
        contentPane.add(panel_1, BorderLayout.SOUTH);

        final JToggleButton btnAutoAddCustomer = new JToggleButton("自动产生顾客");
        btnAutoAddCustomer.addActionListener(e -> autoAddCustomer(btnAutoAddCustomer));
        btnAutoAddCustomer.setPreferredSize(new Dimension(140, 40));
        panel_1.add(btnAutoAddCustomer);

        final JButton btnAddCustomer = new JButton("添加顾客");
        btnAddCustomer.addActionListener(e -> addCustomer());
        btnAddCustomer.setPreferredSize(new Dimension(110, 40));
        panel_1.add(btnAddCustomer);

        final JPanel panel_2 = new JPanel();
        contentPane.add(panel_2, BorderLayout.CENTER);
        panel_2.setLayout(null);

        lblMsg = new JLabel("叫号");
        lblMsg.setFont(new Font("宋体", Font.PLAIN, 22));
        lblMsg.setBounds(37, 13, 415, 51);
        panel_2.add(lblMsg);

        lblLastCustomer = new JLabel("最后一位顾客编号");
        lblLastCustomer.setFont(new Font("宋体", Font.PLAIN, 22));
        lblLastCustomer.setBounds(37, 122, 415, 51);
        panel_2.add(lblLastCustomer);

        lblCustomerCount = new JLabel("现排队人数");
        lblCustomerCount.setFont(new Font("宋体", Font.PLAIN, 22));
        lblCustomerCount.setBounds(37, 66, 415, 51);
        panel_2.add(lblCustomerCount);
    }

    /**
     * Bank system initialization program
     */
    void init() {
        // 监听按钮是否按下，按下 "启动柜员服务"，弹起 "停止柜员服务"
        final ActionListener btnWindowActionListener = e -> {
            // 获取事件源（即开关按钮本身）
            final JToggleButton btn = (JToggleButton) e.getSource();
            final int id = Integer.parseInt(btn.getName());
            final Teller teller = tellers[id];
            if (btn.isSelected()) {
                teller.startServe();
            } else {
                teller.stopServe();
                btn.setText("窗口" + btn.getName() + "：停止服务");
            }
        };

        // 初始化柜台服务人员
        for (int i = 0; i < tellers.length; i++) {
            final Teller teller = new Teller(queue);
            final JToggleButton btn = btnWindows[i];
            // 初始化服务方法
            teller.setListener(customer -> {
                if (customer == null) {
                    btn.setText("窗口" + btn.getName() + "：空闲");
                    return;
                }

                SwingUtilities.invokeLater(() -> {
                    lblMsg.setText("请第 " + customer.getId() + " 号顾客到 " + teller.getId() + " 窗口");
                    btn.setText("服务顾客：" + customer.getId());
                    lblCustomerCount.setText("现排队人数：" + queue.size());
                });
            });

            // 监听按钮是否按下，按下表明柜员服务
            tellers[i] = teller;
            btnWindows[i].addActionListener(btnWindowActionListener);
        }
    }

    /**
     * Add a service customer
     */
    private void addCustomer() {
        final Customer customer = new Customer();
        // 添加顾客
        queue.add(customer);

        SwingUtilities.invokeLater(() -> {
            lblCustomerCount.setText("现排队人数：" + queue.size());
            lblLastCustomer.setText("最后一位顾客编号：" + customer.getId());
        });
    }

    /**
     * Automatically generate and add service costumers
     *
     * @param btn JToggleButton
     */
    @SuppressWarnings("all")
    private void autoAddCustomer(JToggleButton btn) {
        if (btn.isSelected()) {
            autoAddCustomerThread = new Thread(() -> {
                while (true) {
                    try {
                        this.addCustomer();
                        int t = (int) (Math.random() * 5000 + 3000);
                        System.out.printf("> 生成顾客，时间 [%d] 秒\n", t);
                        Thread.sleep(t);
                    } catch (InterruptedException ignored) {
                    }
                }
            });

            autoAddCustomerThread.start();
        } else if (autoAddCustomerThread != null) {
            // 中断生成程序
            autoAddCustomerThread.interrupt();
            autoAddCustomerThread = null;
        }
    }

    /**
     * Launch the application
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            try {
                final Bank frame = new Bank();
                frame.init();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

}
